#ifndef _WX_LOG_H_
#define _WX_LOG_H_

#include "wx/defs.h"

typedef unsigned long wxTraceMask;
typedef unsigned long wxLogLevel;

#include "wx/string.h"
#include "wx/arrstr.h"
#include <time.h>
#include "wx/dynarray.h"

#define wxUSE_LOG_DEBUG 0


class wxTextCtrl;
class wxLogFrame;
class wxFrame;
class wxWindow;

enum {
  wxLOG_FatalError,
  wxLOG_Error,
  wxLOG_Warning,
  wxLOG_Message,
  wxLOG_Status,
  wxLOG_Info,
  wxLOG_Debug,
  wxLOG_Trace,
  wxLOG_Progress,
  wxLOG_User = 100,
  wxLOG_Max = 10000
};

class wxLog {
  public:
    wxLog() {}
    static bool IsEnabled() { return ms_doLog; }
    static bool EnableLogging( bool doIt = true ) { bool doLogOld = ms_doLog; ms_doLog = doIt; return doLogOld; }
    static void OnLog( wxLogLevel level, const wxChar *szString, time_t t );
    virtual void Flush();
    static void FlushActive() {
      if( !ms_suspendCount ) {
        wxLog *log = GetActiveTarget();
        if( log ) {
          log->Flush();
        }
      }
    }
    static wxLog *GetActiveTarget();
    static wxLog *SetActiveTarget( wxLog *pLogger );
    static void Suspend() { ms_suspendCount++; }
    static void Resume() { ms_suspendCount--; }
    static void SetVerbose( bool bVerbose = true ) { ms_bVerbose = bVerbose; }
    static void SetLogLevel( wxLogLevel logLevel ) { ms_logLevel = logLevel; }
    static void DontCreateOnDemand();
    static void DoCreateOnDemand();
    static void SetRepetitionCounting( bool bRepetCounting = true ) { ms_bRepetCounting = bRepetCounting; }
    static bool GetRepetitionCounting() { return ms_bRepetCounting; }
    static void SetTraceMask( wxTraceMask ulMask ) { ms_ulTraceMask = ulMask; }
    static void AddTraceMask( const wxString& str ) { ms_aTraceMasks.push_back( str ); }
    static void RemoveTraceMask( const wxString& str );
    static void ClearTraceMasks();
    static const wxArrayString &GetTraceMasks() { return ms_aTraceMasks; }
    static void SetTimestamp( const wxChar *ts ) { ms_timestamp = ts; }
    static bool GetVerbose() { return ms_bVerbose; }
    static wxTraceMask GetTraceMask() { return ms_ulTraceMask; }
    static bool IsAllowedTraceMask( const wxChar *mask );
    static wxLogLevel GetLogLevel() { return ms_logLevel; }
    static const wxChar *GetTimestamp() { return ms_timestamp; }
    static void TimeStamp( wxString *str );
    virtual ~wxLog();
    bool HasPendingMessages() const { return true; }
    wxDEPRECATED( static wxChar *SetLogBuffer( wxChar *buf, size_t size = 0 ) );
  protected:
    virtual void DoLog( wxLogLevel level, const wxChar *szString, time_t t );
    virtual void DoLogString( const wxChar *szString, time_t t );
    static unsigned DoLogNumberOfRepeats();
  private:
    static bool        ms_bRepetCounting;
    static wxString    ms_prevString;
    static unsigned    ms_prevCounter;
    static time_t      ms_prevTimeStamp;
    static wxLogLevel  ms_prevLevel;
    static wxLog      *ms_pLogger;
    static bool        ms_doLog;
    static bool        ms_bAutoCreate;
    static bool        ms_bVerbose;
    static wxLogLevel  ms_logLevel;
    static size_t      ms_suspendCount;
    static const wxChar *ms_timestamp;
    static wxTraceMask ms_ulTraceMask;
    static wxArrayString ms_aTraceMasks;
    unsigned LogLastRepeatIfNeeded();
    unsigned LogLastRepeatIfNeededUnlocked();
};

class wxLogBuffer : public wxLog {
  public:
    wxLogBuffer() { }
    const wxString& GetBuffer() const { return m_str; }
    virtual void Flush();
  protected:
    virtual void DoLog( wxLogLevel level, const wxChar *szString, time_t t );
    virtual void DoLogString( const wxChar *szString, time_t t );
  private:
    wxString m_str;
    DECLARE_NO_COPY_CLASS( wxLogBuffer )
};

class wxLogStderr : public wxLog {
  public:
    wxLogStderr( FILE *fp = ( FILE * ) NULL );
  protected:
    virtual void DoLogString( const wxChar *szString, time_t t );
    FILE *m_fp;
    DECLARE_NO_COPY_CLASS( wxLogStderr )
};

class wxLogStream : public wxLog {
  public:
    wxLogStream( std::ostream *ostr = ( std::ostream * ) NULL );
  protected:
    virtual void DoLogString( const wxChar *szString, time_t t );
    std::ostream *m_ostr;
};

class wxLogNull {
  public:
    wxLogNull() : m_flagOld( wxLog::EnableLogging( false ) ) { }
    ~wxLogNull() { ( void )wxLog::EnableLogging( m_flagOld ); }
  private:
    bool m_flagOld;
};

class wxLogChain : public wxLog {
  public:
    wxLogChain( wxLog *logger );
    virtual ~wxLogChain();
    void SetLog( wxLog *logger );
    void PassMessages( bool bDoPass ) { m_bPassMessages = bDoPass; }
    bool IsPassingMessages() const { return m_bPassMessages; }
    wxLog *GetOldLog() const { return m_logOld; }
    virtual void Flush();
    void DetachOldLog() { m_logOld = NULL; }
  protected:
    virtual void DoLog( wxLogLevel level, const wxChar *szString, time_t t );
  private:
    wxLog *m_logNew;
    wxLog *m_logOld;
    bool m_bPassMessages;
    DECLARE_NO_COPY_CLASS( wxLogChain )
};

class wxLogPassThrough : public wxLogChain {
  public:
    wxLogPassThrough();
  private:
    DECLARE_NO_COPY_CLASS( wxLogPassThrough )
};

#include "wx/generic/logg.h"

unsigned long wxSysErrorCode();
const wxChar* wxSysErrorMsg( unsigned long nErrCode = 0 );

class wxFrame;

extern void wxVLogFatalError( const wxChar *szFormat, va_list argptr );
extern void wxLogFatalError( const wxChar *szFormat, ... );
extern void wxVLogError( const wxChar *szFormat, va_list argptr );
extern void wxLogError( const wxChar *szFormat, ... );
extern void wxVLogWarning( const wxChar *szFormat, va_list argptr );
extern void wxLogWarning( const wxChar *szFormat, ... );
extern void wxVLogMessage( const wxChar *szFormat, va_list argptr );
extern void wxLogMessage( const wxChar *szFormat, ... );
extern void wxVLogInfo( const wxChar *szFormat, va_list argptr );
extern void wxLogInfo( const wxChar *szFormat, ... );
extern void wxVLogVerbose( const wxChar *szFormat, va_list argptr );
extern void wxLogVerbose( const wxChar *szFormat, ... );
extern void wxVLogStatus( const wxChar *szFormat, va_list argptr );
extern void wxLogStatus( const wxChar *szFormat, ... );
extern void wxVLogSysError( const wxChar *szFormat, va_list argptr );
extern void wxLogSysError( const wxChar *szFormat, ... );
extern void wxVLogDebug( const wxChar *szFormat, va_list argptr );
extern void wxLogDebug( const wxChar *szFormat, ... );
extern void wxVLogStatus( wxFrame * pFrame, const wxChar *szFormat, va_list argptr );
extern void wxLogStatus( wxFrame * pFrame, const wxChar *szFormat, ... );
extern void wxVLogSysError( long lErrCode, const wxChar *szFormat, va_list argptr );
extern void wxLogSysError( long lErrCode, const wxChar *szFormat, ... );
extern void wxVLogTrace( const wxChar* mask, const wxChar *szFormat, va_list argptr );
extern void wxLogTrace( const wxChar*, const wxChar *szFormat, ... );
extern void wxVLogTrace( wxTraceMask mask, const wxChar *szFormat, va_list argptr );
extern void wxLogTrace( wxTraceMask mask, const wxChar *szFormat, ... );
extern void wxVLogGeneric( wxLogLevel level, const wxChar *szFormat, va_list argptr );
extern void wxLogGeneric( wxLogLevel level, const wxChar *szFormat, ... );

void wxSafeShowMessage( const wxString& title, const wxString& text );

#define wxLogApiError(api, rc)                                            \
  wxLogDebug(wxT("In file %s at line %d: '%s' failed with ")            \
             wxT("error 0x%08lx (%s)."),                                \
             __TFILE__, __LINE__, api,                                  \
             (long)rc, wxSysErrorMsg(rc))
#define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode())

#endif
